package vben.core.framework.security.authc;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import vben.core.common.mvc.api.R;
import vben.core.framework.config.AppConfig;
import vben.core.framework.cache.RedisHandler;
import vben.core.framework.security.authz.JwtHandler;
import vben.core.framework.security.pojo.*;
import vben.core.framework.sms.enums.SmsTypeEnum;
import vben.core.framework.sms.service.SmsService;
import vben.core.framework.sms.vo.SmsVo;
import vben.core.module.mon.log.login.MonLogLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import vben.core.module.sys.org.user.SysOrgUserService;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.websocket.server.PathParam;
import java.util.HashMap;
import java.util.Map;

//认证API:主要包含登录登出、token刷新、菜单获取、用户信息获取
@RestController
public class AuthcApi {

    //登录
    @PostMapping("/login")
    public R login(@Valid @RequestBody LoginVo loginVo, HttpServletRequest request) {
        //1.登录验证
        UserDo userDo =  authcService.getDbUserByUsername(loginVo.getUsername());
        boolean passFlag = authcService.check(userDo, loginVo);
        if (!passFlag) {
            return R.build(402, "账号不存在或密码错误");
        }

        //2.创建accessToken与refreshToken
//        String atokenUUID = IdUtil.simpleUUID();
//        String atoken = jwtHandler.createTokenByUuid(atokenUUID);
//        String rtoken = jwtHandler.createTokenByUuid(loginVo.getUsername());//需要加密下
//
//        Map<String, Object> backMap = new HashMap<>();
//        backMap.put("token", atoken);
//        backMap.put("rtoken", rtoken);
//
//        //3.初始化用户信息，获取门户，菜单与按钮
//        //Zuser zuser = new Zuser(userDo.getId(), userDo.getName(), loginVo.getUsername(),userDo.getCorid(),userDo.getType());
//        Zuser zuser = new Zuser(userDo);
//        authcService.initZuser(zuser, userDo, backMap); //这个方法非常重要
//
//        redisHandler.set("online-key:" + atokenUUID, zuser, appConfig.getJwt().getAtime());//默认8小时过期
//
//        //4.异步方式记录登录日志
//        monLogLoginService.save("online-key:" + atokenUUID, zuser, request);
        return R.ok(getBackMap(userDo,request));
    }

    //注册
    @PostMapping(value = "auth/register")
    public R register(@Validated @RequestBody RegisterVo registerVo) {
        // 验证
        smsService.verifySms(registerVo.getPhone(), registerVo.getCode(), SmsTypeEnum.REGISTERED);
        // 注册
        userService.register(registerVo);
        return R.ok("注册成功，请登录",null);
    }

    @PostMapping("/auth/sendCode")
    public R sendCode(@Validated @RequestBody SmsVo smsVo) {
        return R.ok(smsService.sendSms(smsVo)).put("msg", "验证码已发送");
    }


    @PostMapping("/auth/loginByCode")
    public R loginByCode(@Validated @RequestBody LoginByCodeVo codeVo,HttpServletRequest request) {
        smsService.verifySms(codeVo.getPhone(), codeVo.getCode(), SmsTypeEnum.LOGIN);
        UserDo userDo =  authcService.getDbUserByUsername(codeVo.getPhone());

        return R.ok(getBackMap(userDo,request));
    }

    private Map<String, Object> getBackMap(UserDo userDo,HttpServletRequest request){
        //2.创建accessToken与refreshToken
        String atokenUUID = IdUtil.simpleUUID();
        String atoken = jwtHandler.createTokenByUuid(atokenUUID);
        String rtoken = jwtHandler.createTokenByUuid(userDo.getUsnam());//需要加密下

        Map<String, Object> backMap = new HashMap<>();
        backMap.put("token", atoken);
        backMap.put("rtoken", rtoken);

        //3.初始化用户信息，获取门户，菜单与按钮
        //Zuser zuser = new Zuser(userDo.getId(), userDo.getName(), loginVo.getUsername(),userDo.getCorid(),userDo.getType());
        Zuser zuser = new Zuser(userDo);
        authcService.initZuser(zuser, userDo, backMap); //这个方法非常重要

        redisHandler.set("online-key:" + atokenUUID, zuser, appConfig.getJwt().getAtime());//默认8小时过期

        //4.异步方式记录登录日志
        monLogLoginService.save("online-key:" + atokenUUID, zuser, request);
        return backMap;
    }



    //登出
    @GetMapping("/logout")
    public R logout(Authentication auth) {
        return R.ok();
    }



    //token刷新
    @GetMapping("/rtoken")
    public R rtoken(@PathParam("token2") String token2) {
        System.out.println("token2=" + token2);
        String username = jwtHandler.getClaims(token2).getId();
        System.out.println("username=" + username);
        String uuid = IdUtil.simpleUUID();
        String token = jwtHandler.createTokenByUuid(uuid);
        Zuser zuser = authcService.getUser(username);
        redisHandler.set(uuid, zuser, 10000 / 1000);
        Map<String, Object> backMap = new HashMap<>();
        backMap.put("token", token);
        return R.ok(backMap);
    }

    //获取用户信息
    @GetMapping("/getUserInfo")
    public R getUserInfo(Authentication auth, HttpServletRequest request) {
        Zuser zuser = (Zuser) auth.getPrincipal();
        return R.ok(zuser);
    }

    //获取菜单树
    @GetMapping("/getMenuList")
    public R getMenuList(String porid, Authentication auth, HttpServletRequest request) {
        if (auth == null) {
            return R.build(401, "登录过期");
        }
        Map<String, Object> backMap = new HashMap<>();
        Zuser zuser = (Zuser) auth.getPrincipal();

        if (StrUtil.isBlank(porid)) {
            UserDo userDo= authcService.getDbUserById(zuser.getId());
            authcService.initZuser(zuser, userDo, backMap);
        } else {
            authcService.switchPortal(zuser, backMap, porid);
        }
        return R.ok(backMap);
    }

    @Autowired
    private AuthcService authcService;

    @Autowired
    private AppConfig appConfig;

    @Autowired
    private RedisHandler redisHandler;

    @Autowired
    private JwtHandler jwtHandler;

    @Autowired
    private MonLogLoginService monLogLoginService;

    @Autowired
    private SysOrgUserService userService;

    @Autowired
    private SmsService smsService;


}
